package org.dromara.crawler.mongo.mongoservice.impl;

import cn.hutool.core.util.ObjectUtil;
import com.mongoplus.aggregate.Aggregate;
import com.mongoplus.aggregate.AggregateWrapper;
import com.mongoplus.aggregate.pipeline.Accumulators;
import com.mongoplus.conditions.interfaces.ConditionOperators;
import com.mongoplus.conditions.query.LambdaQueryChainWrapper;
import com.mongoplus.mapping.TypeReference;
import com.mongoplus.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.bson.Document;
import org.dromara.crawler.domain.bo.ElementEventBo;
import org.dromara.crawler.domain.vo.ElementEventVo;
import org.dromara.crawler.mongo.mongodomain.ElementEvent;
import org.dromara.crawler.mongo.mongodomain.ElementTarget;
import org.dromara.crawler.mongo.mongodomain.EventEventEdges;
import org.dromara.crawler.mongo.mongodomain.HotspotEvent;
import org.dromara.crawler.mongo.mongoservice.EventEventEdgesService;
import org.dromara.crawler.utils.DocConvertUtil;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class EventEventEdgesServiceImpl extends ServiceImpl<EventEventEdges> implements EventEventEdgesService {


    @Override
    public Map<String,List<EventEventEdges>> getRelation(List<String> eventIds) {
        Map<String,List<EventEventEdges>>  resultMap = new HashMap<>();
        AggregateWrapper edgesAggregate = new AggregateWrapper();
        LambdaQueryChainWrapper<EventEventEdges> wrapper = createWrapper(eventIds);
        edgesAggregate
            .match(wrapper)
            .group("$src", Accumulators.push("docs", "$$ROOT"));
        List<Document> documentList = execute("event_event_edges", edgesAggregate, Document.class);
        documentList.stream().forEach(document -> {
            List<EventEventEdges> list = DocConvertUtil.toEntityList(document.getList("docs",Document.class),EventEventEdges.class);
            resultMap.put(document.getString("_id"), list);
        });
        return resultMap;
    }

    @Override
    public List<EventEventEdges> getEdgesByTargetId(String targetId) {
        LambdaQueryChainWrapper<EventEventEdges> wrapper = this.lambdaQuery();
        LambdaQueryChainWrapper<EventEventEdges> orWrapper = this.lambdaQuery();
        orWrapper.eq(EventEventEdges::getSrc, targetId);
        orWrapper.eq(EventEventEdges::getDst, targetId);
        wrapper.or(orWrapper);
        return list(wrapper);
    }


    private LambdaQueryChainWrapper createWrapper(List<String> eventIds) {
        LambdaQueryChainWrapper<EventEventEdges> wrapper = this.lambdaQuery();
        LambdaQueryChainWrapper<EventEventEdges> orWrapper = this.lambdaQuery();
        orWrapper.in(EventEventEdges::getSrc, eventIds);
        orWrapper.in(EventEventEdges::getDst, eventIds);
        wrapper.or(orWrapper);
        return wrapper;
    }



    private List<Map<String, Object>> execute(String collectionName, Aggregate<?> aggregate) {
        return baseMapper.aggregateList(collectionName, aggregate, new TypeReference<Map<String, Object>>() {
        });
    }


    private <T> List<T> execute(String collectionName, Aggregate<?> aggregate, Class<T> clazz) {
        return baseMapper.aggregateList(collectionName, aggregate, clazz);
    }


}
